<?php

/**
 * 循环队列
 * 顺序队列只是修改队头和队尾的指针记录，但是数组会一直增加，会导致这一个数组占满内存，不是一个好的队列实现。
 * 如果不想浪费内存空间,可以使用循环队列,在有限的数组空间范围内，当达到数组的最大值时，将新的数据保存回之前的下标位置。
 */

define('MAX_QUEUE_LENGTH', 6);

class SqQueue {
    public $data;
    public $front; //队列头部
    public $rear; //队列尾部
}

function InitSqQueue() {
    $queue = new SqQueue();
    $queue->data = [];
    $queue->front = 0;
    $queue->rear = 0;
    return $queue;
}

function EnSqQueueLoop(SqQueue &$queue, $e) {
    // 判断队列是否满了
    if (($queue->rear + 1) % MAX_QUEUE_LENGTH == $queue->front) {
        return false;
    }
    $queue->data[$queue->rear] = $e;
    $queue->rear = ($queue->rear + 1) % MAX_QUEUE_LENGTH; // 改成循环下标
}

function DeSqQueueLoop(SqQueue &$queue) {
    // 队列为空
    if ($queue->front == $queue->rear) {
        return false;
    }
    $e = $queue->data[$queue->front];
    unset($queue->data[$queue->front]);
    $queue->front = ($queue->front + 1) % MAX_QUEUE_LENGTH; // 改成循环下标
    return $e;
}

$q = InitSqQueue();
//入队6个元素
EnSqQueueLoop($q, 'A');
EnSqQueueLoop($q, 'B');
EnSqQueueLoop($q, 'C');
EnSqQueueLoop($q, 'D');
EnSqQueueLoop($q, 'E');
EnSqQueueLoop($q, 'F');
print_r($q);
/*
SqQueue Object
(
    [data] => Array
        (
            [0] => A
            [1] => B
            [2] => C
            [3] => D
            [4] => E
        )

    [front] => 0
    [rear] => 5
)
*/

//出队2个元素
echo DeSqQueueLoop($q), PHP_EOL; //A
echo DeSqQueueLoop($q), PHP_EOL; //B
print_r($q);
/*
SqQueue Object
(
    [data] => Array
        (
            [2] => C
            [3] => D
            [4] => E
        )

    [front] => 2
    [rear] => 5
)
*/

//入队3个元素
EnSqQueueLoop($q, 'F');
EnSqQueueLoop($q, 'G');
EnSqQueueLoop($q, 'H');
print_r($q);
/*
SqQueue Object
(
    [data] => Array
        (
            [2] => C
            [3] => D
            [4] => E
            [5] => F
            [0] => G
        )

    [front] => 2
    [rear] => 1
)
*/